#pragma once
#ifndef BUFFER_H
#define BUFFER_H

#include <vector>
#include <unordered_map>
#include <thread>
#include <atomic>
#include <mutex>
#include <memory>
#include <future>
#include <climits>

using namespace std;

class Page;

//缓冲区页帧
struct BufferPage {
    BufferPage* next = nullptr;
    shared_ptr<Page> page = nullptr;
    atomic<int> accessCount{ 0 };
    mutex pageMutex;
};


class Buffer {
public:
    static Buffer* getInstance();
    static void release();
    ~Buffer();


    void initialBuffer();
    Page* getPage(string fileid, string pageid);
    Page* getPageAsync(string fileid, string pageid);
    void deleteBufferPage(string fileid, string pageid);
    void deleteBufferPageAsync(string fileid, string pageid);
    void print();

    //��־���
    void logBufferStats();
    void logBufferStatsAsync();
    void writeStatsToLogFile(const string& filename);
    void writeStatsToLogFileAsync(const string& filename);

private:
    Buffer() {
        head = nullptr;
        stopMonitor = false;
        totalRequests = 0; hitCount = 0; missCount = 0;
    }
    //����
    Buffer(const Buffer&) = delete;
    Buffer& operator=(const Buffer&) = delete;
    static Buffer* instance;


    BufferPage* head = nullptr;
    mutable mutex bufferMutex;
    atomic<int> hitCount{ 0 }, missCount{ 0 }, totalRequests{ 0 };

    //����߳�
    thread monitorThread;
    atomic<bool> stopMonitor{ false };
    void monitorPerformance();
    void startMonitorThread();
    void stopMonitorThread();

    //LRU
    BufferPage* findBufferPage(const string& fileid, const string& pageid);
    void updateLRU(BufferPage* accessedPage);

    //�첽��д
    void safeAsyncWrite(std::shared_ptr<Page> page);
    void safeAsyncRead(std::shared_ptr<Page> page);

    //����ҳ
    void promoteHotPages();
    void demoteColdPages();
    void promoteToFront(BufferPage* hotPage);
    BufferPage* findColdestPage();
    int getHotPageThreshold() const;

    //Ԥȡ
    atomic<bool> enablePrefetch{ true };
    double prefetchThreshold = 70.0;
    void markHotPage(const string& fileid, const string& pageid);
    void prefetchNextPage(const string& fileid, const string& pageid);
    void prefetchNextPageAsync(const string& fileid, const string& pageid);
    unordered_map<string, atomic<int>> pageAccessCount;

    //�滻��־
    void logPageReplacement(const string& oldFileId, const string& oldPageId,
        const string& newFileId, const string& newPageId,
        const string& reason = "LRU");
    void logPageReplacementAsync(const string& oldFileId, const string& oldPageId,
        const string& newFileId, const string& newPageId,
        const string& reason = "LRU");
    atomic<int> replacementCount{ 0 };

    //�����л�
    enum class ReplacePolicy : char { LRU = 0, LFU = 1 };
    ReplacePolicy curPolicy = ReplacePolicy::LRU;//Ĭ����LRU
    static constexpr int STAT_WINDOW = 50;
    atomic<int> recentReplaceCnt{ 0 }, reloadInWindow{ 0 };

    struct LFUEntry {
        BufferPage* bp;
        int freq;
        bool operator<(const LFUEntry& o) const { return freq > o.freq; }//��С�� �Ѷ���Զ�Ƿ���Ƶ����͵�
    };
    vector<LFUEntry> lfuHeap{ 1 };              // �±� 0 ռλ
    unordered_map<BufferPage*, size_t> bp2idx;  // ҳ�浽��������ӳ��

    void recordReplace(BufferPage* victim);
    void recordReload(const string& fileid, const string& pageid);
    void trySwitchPolicy();
    void switchToLRU();
    void switchToLFU();
    void lfuBuildHeap();//������С��
    void lfuUpdateFreq(BufferPage* bp); //����ҳ�����Ƶ�ʲ�������
    BufferPage* lfuPickVictim(); //ѡ��Ҫ��̭��ҳ��
    void optimizeByMetrics(double hitRate);
};

#endif // !BUFFER_H